package com.handu.luna.core.domain.promotion;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import javax.persistence.Entity;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient;
import javax.persistence.criteria.*;
import javax.validation.constraints.Size;

import com.handu.luna.core.domain.search.CreditPromotionSearch;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.format.annotation.DateTimeFormat;



@Entity
public class CreditPromotion extends Promotion {

     public static final String DELIMITER = ",";

    public enum CreditCategory {

        LEVEL("等级积分"), CONSUME("消费积分");
        public String description;
        CreditCategory(final String description) {
			this.description = description;
		}

        public static CreditCategory valueOf(int ordinal) {
            if (ordinal < 0 || ordinal >= values().length) {
                throw new IndexOutOfBoundsException("Invalid ordinal");
            }
            return values()[ordinal];
        }
    }

    public enum CreditType {

		CREDIT("积分"), MULTIPLE("倍数");
		public String description;

        CreditType(final String description) {
			this.description = description;
		}
	}

    @Override
    public String getStatus() {
        return initStatus(this.getStartTime(), this.getEndTime());
    }

    private CreditType creditType;
    private String creditCategorys;

	@Size(min=1,max=100, message="最多100个字")
	private String creditName;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date startTime;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date endTime;
	private String[] userRank;
	private String descirption;
    @Transient private List<CreditCategory> creditCategoryList;

    @PrePersist
    public void prePersist() {
        if(CollectionUtils.isNotEmpty(creditCategoryList)) {
            this.setCreditCategorys(this.listToStr(creditCategoryList));
        }
    }

    public void update() {
        prePersist();
        context.getCreditPromotionRepository().saveAndFlush(this);
    }

    @PostLoad
    public void init() {
        if(StringUtils.isNotBlank(creditCategorys)) {
            this.setCreditCategoryList(this.strToList(creditCategorys));
        }
    }

    public String listToStr(List<CreditCategory> creditCategoryList) {
        StringBuilder sb = new StringBuilder("");
        for(CreditCategory creditCategory : creditCategoryList) {
            sb.append(creditCategory.ordinal());
            sb.append(",");
        }
        return sb.toString();
    }

    public List<CreditCategory> strToList(String creditCategorys) {
        List<CreditCategory> creditCategoryArrayList = new ArrayList<>();
        for(String index : creditCategorys.split(DELIMITER)) {
            CreditCategory creditCategory = CreditCategory.valueOf(Integer.parseInt(index));
            creditCategoryArrayList.add(creditCategory);
        }
        return creditCategoryArrayList;
    }


     public static Specification<CreditPromotion> selectCondition(CreditPromotionSearch creditPromotionSearch) {

        return new Specification<CreditPromotion>() {
			@Override
			public Predicate toPredicate(Root<CreditPromotion> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				Predicate predicate = builder.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();

				if (StringUtils.isNotBlank(creditPromotionSearch.getName())) {
					expressions.add(builder.like(root.<String> get("creditName"),"%"+creditPromotionSearch.getName() +"%"));
				}

				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date date1 = null;
				Date date2 = null;

				if(StringUtils.isNotBlank(creditPromotionSearch.getStartDate())){
					try {
						date1 = sdf.parse(creditPromotionSearch.getStartDate());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.greaterThanOrEqualTo(root.<Date>get("startTime"), date1));
				}

				if(StringUtils.isNotBlank(creditPromotionSearch.getEndDate())){
					try {
						date2 = sdf.parse(creditPromotionSearch.getEndDate());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.lessThanOrEqualTo(root.<Date>get("startTime"), date2));
				}

                if(StringUtils.isNotBlank(creditPromotionSearch.getStatus())) {
                   if(creditPromotionSearch.getStatus().equals(PromotionStatus.UNACTIVATED.description)) {
                       expressions.add(builder.greaterThan(root.<Date>get("startTime"), new Date()));
                   }else if(creditPromotionSearch.getStatus().equals(PromotionStatus.ACTIVATING.description)) {
                       expressions.add(builder.lessThan(root.<Date>get("startTime"), new Date()));
                       expressions.add(builder.greaterThan(root.<Date>get("endTime"), new Date()));
                   }else if(creditPromotionSearch.getStatus().equals(PromotionStatus.ACTIVATED.description)){
                       expressions.add(builder.lessThan(root.<Date>get("endTime"), new Date()));
                   }
                }

				return query.where(predicate).getRestriction();

			}
		};
    }

    public CreditType getCreditType() {
        return creditType;
    }

    public void setCreditType(CreditType creditType) {
        this.creditType = creditType;
    }

    public String getCreditCategorys() {
        return creditCategorys;
    }

    public void setCreditCategorys(String creditCategorys) {
        this.creditCategorys = creditCategorys;
    }

    public List<CreditCategory> getCreditCategoryList() {
        return creditCategoryList;
    }

    public void setCreditCategoryList(List<CreditCategory> creditCategoryList) {
        this.creditCategoryList = creditCategoryList;
    }

    public String getCreditName() {
		return creditName;
	}
	public void setCreditName(String creditName) {
		this.creditName = creditName;
	}


    public Date getStartTime() {
		return startTime;
	}
	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}
	public Date getEndTime() {
		return endTime;
	}
	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}
	public String[] getUserRank() {
		return userRank;
	}
	public void setUserRank(String[] userRank) {
		this.userRank = userRank;
	}
	public String getDescirption() {
		return descirption;
	}
	public void setDescirption(String descirption) {
		this.descirption = descirption;
	}

}
